using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace RSSRadio.Utility
{
    public class CustomThreadPool
    {
        private bool stopping = false;
        private Queue<Job> queue = new Queue<Job>();
        private ManualResetEvent pendingRequests = new ManualResetEvent(false); 
        


        public CustomThreadPool(int numThreads)
        {
            //Initialize threads
            for(int i = 0 ; i< numThreads ; i++)
            {
                Thread t = new Thread(new ThreadStart(this.RunnerThread));
                //Set threads to background
                t.IsBackground = true;
                t.Start();
            }
        }

        public void QueueUserWorkItem(WaitCallback callback)
        {
            QueueUserWorkItem(callback,null);
        }

        public void QueueUserWorkItem(WaitCallback callback, object parameters)
        {
            lock(queue)
            {
                Job job = new Job(callback,parameters);
                queue.Enqueue(job);
                pendingRequests.Set();
            }
        }
        public void Stop()
        {
            lock(queue)
            {
                stopping = true;
                //Unlock the waiting threads
                pendingRequests.Set();
            }
            //Sleep a little while to allow free workers to exit; busy workers will exit when possible
            Thread.Sleep(20);
            
        }
        public void RunnerThread()
        {
            Job job = null;
            while(!stopping)
            {

                //Wait until we get something from the queue
                while (job == null && !stopping)
                {
                    //Wait until a request shows up
                    pendingRequests.WaitOne();
                    //Try to get it
                    lock(queue)
                    {
                        if(queue.Count > 0)
                        {
                            job = queue.Dequeue();
                        }
                        if(queue.Count == 0)
                        {
                            //If we just got the last request, clear the pending request flag to force other threads to wait
                            pendingRequests.Reset();
                        }
                    }
                }

                if(stopping) break;
 
                try
                {
                    job.Callback.Invoke(job.Paramters);
                }
                catch(Exception ex)
                {
                    Globals.logError(ex);
                }
                job = null;
            }
        }

        private class Job
        {
            private WaitCallback callback;

            private object paramters;

            public Job(WaitCallback callback, object paramters)
            {
                this.callback = callback;
                this.paramters = paramters;
            }

            public WaitCallback Callback
            {
              get { return callback; }
              set { callback = value; }
            }
            public object Paramters
            {
              get { return paramters; }
              set { paramters = value; }
            }
        }

    }
}
